package com.ostrich.manpower.common;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.base.util.SpringContextUtil;
import com.ostrich.system.analysis.FormulaAnalysis;
import com.ostrich.system.analysis.FormulaAnalysisDao;
import com.ostrich.system.bean.TostSysFormulainfo;
import com.ostrich.system.service.impl.TostSysFormulainfoService;

@Component
public class FormulaUtil {
	@Autowired
	private static SpringContextUtil springContextUtil;
	@Autowired
	private static TostSysFormulainfoService fmservice;
	
	@Autowired(required=false)
	private static FormulaAnalysisDao formulaanalysisdao;
	// 缓存的公式信息
	private static Map<Integer, TostSysFormulainfo> fminfo;

	/***
	 * 调用公式
	 * 
	 * @param id
	 * @param obj
	 * @return
	 */
	public static Map<String, Object> formulaById(Integer id, Object... obj) {
		TostSysFormulainfo fm = getFminfo(id);
		if (fm != null) {
			// 类型为1的表示简单运算的方法处理
			if (("1").equalsIgnoreCase(fm.getFmType())) {
				return getFormuByArithmetic(fm, obj);
			} else if ("2".equalsIgnoreCase(fm.getFmType())) {
				return getFormuByOther(fm, obj);
			} else if ("3".equalsIgnoreCase(fm.getFmType())||"4".equalsIgnoreCase(fm.getFmType())) {
				// 3表示使用sql运算的方法处理
				return getFormuForMapBySql(fm, obj);
			}
		}
		return null;
	}

	/****
	 * 根据四则运算符号，进行简单的元算
	 */
	public static Map<String, Object> getFormuByOther(TostSysFormulainfo fm, Object[] obj) {
		Map<String, Object> rt = new LinkedHashMap<String, Object>();
		if (obj != null) {
			// 获得公式的对象信息
			String fmgs = fm.getFmFmexp();
			// 获取返回值
			String[] rs = fm.getFmReturn().split(",");
			for (int i = 0; i < obj.length; i++) {
				fmgs = fmgs.replaceAll("#" + (i + 1) + "#",String.valueOf(obj[i]));// ???
			}
			// 循环运算
			String[] gssp = fmgs.split("\\|");
			for (int i = 0; i < gssp.length; i++) {
				double tp = MathString.cacComplex(gssp[i]);
				Float d = new Float(tp);
				BigDecimal b = new BigDecimal(d); 
				float f1 = b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue(); 
				rt.put(rs[i],f1);
			}
		}
		return rt;
	}

	/***
	 * 一般算法的方法，传递公式对象，及参数对象信息。返回Map对象。
	 * 
	 * @param fm
	 * @param obj
	 * @return
	 */
	public static Map<String, Object> getFormuByArithmetic(
			TostSysFormulainfo fm, Object[] obj) {
		FormulaAnalysis fmay = new FormulaAnalysis();
		if (obj != null) {
			// 进行方法名称获取，然后返回方法对象
			Method sAge;
			try {
				sAge = fmay.getClass().getMethod(fm.getFmFunction(),
						obj.getClass());
				// 执行方法，并且返回方法的返回值信息 传类对象跟参数对象
				Object c = sAge.invoke(fmay, new Object[] { obj });
				return getMap(fm.getFmReturn(), c);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**************
	 * 通过sql语句查询语句
	 * @param fm
	 * @param obj
	 * @return
	 */
	private static Map<String, Object> getFormuForMapBySql(TostSysFormulainfo fm, Object[] obj) {
		String sql = fm.getFmFmulasql();
		if (formulaanalysisdao == null)
			formulaanalysisdao = (FormulaAnalysisDao) SpringContextUtil.getBean("formulaAnalysisDao");
		List<Map<String, Object>> list = formulaanalysisdao.queryBysql(sql, obj);
		if (list != null && list.size() > 0) {
			if (fm.getFmType().equals("4")) {
				Map<String, Object> rtmap = new HashMap<String, Object>();
				rtmap.put("data", list);
				rtmap.put("totle", list.size());
				return rtmap;
			} else {
				return list.get(0);
			}
		} else
			return null;
	}
	

	/***
	 * obj对象信息进行转化为map对象
	 * 
	 * @param obj
	 * @return
	 */
	private static Map<String, Object> getMap(String name, Object obj) {
		Map<String, Object> map = new HashMap<String, Object>();
		// 判断返回对象是否为map，如果为map就不进行处理，如果不是，就put到一个map值中。
		String clname = obj.getClass().getSimpleName();
		// 统一转化为小写然后进行判断
		clname = (clname != null) ? clname.toLowerCase() : clname;
		if (obj != null && clname.indexOf("map") >= 0) {
			return (Map<String, Object>) obj;
		} else {
			map.put(name, obj);
		}
		return map;
	}

	@PostConstruct
	public void init() {
		setFm();
	}

	/****
	 * 设置缓存内的公式信息
	 */
	public static void setFm() {
		if (fminfo == null) {
			fminfo = new LinkedHashMap<Integer, TostSysFormulainfo>();
		}
		// 获取注入的service的bean信息
		if (fmservice == null)
			fmservice = (TostSysFormulainfoService) SpringContextUtil
					.getBean("tostSysFormulainfoService");
		List<TostSysFormulainfo> ls = fmservice.queryByAll();
		if (ls != null)
			for (TostSysFormulainfo fm : ls) {
				fminfo.put(fm.getId(), fm);
			}
	}

	public static void refresh() {
		fminfo.clear();
		setFm();
	}

	/****
	 * 根据id获取公式信息
	 * 
	 * @param id
	 * @return
	 */
	public static TostSysFormulainfo getFminfo(Integer id) {
		if (fminfo != null)
			return fminfo.get(id);
		else
			return null;
	}

}
